package util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.w3c.dom.Document;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class HttpUtil {

    private String url;
    private Map<String,Object> config;

    public HttpUtil(){}

    public HttpUtil(String url){
        this(url,null);
    }

    public HttpUtil(Map<String,Object> config){
        this(null,config);
    }

    public HttpUtil(String url,Map<String,Object> config){
        this.url = url;
        this.config = config;
    }

    public Result get(){
        return get(this.url,this.config);
    }

    public Result get(String url){
        return get(url,this.config);
    }

    public Result get(String url, Map<String,Object> config){
        if(config==null) config=new HashMap<>();
        try(CloseableHttpClient httpclient = HttpClients.createDefault()){
            HttpGet httpGet = new HttpGet(url);
            try(CloseableHttpResponse response = httpclient.execute(httpGet)){
                HttpEntity entify = response.getEntity();
                return new Result(EntityUtils.toString(entify));
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public Result post(String data){
        return post(this.url,data,this.config);
    }

    public Result post(String data,Map<String,Object> config){
        return post(this.url,data,config);
    }

    public Result post(String url,String data){
        return post(url,data,this.config);
    }

    public Result post(String url,String data,Map<String,Object> config){
        if(config==null) config=new HashMap<>();
        try(CloseableHttpClient httpclient = HttpClients.createDefault()){
            HttpPost httpPost = new HttpPost(url);
            StringEntity content = new StringEntity(data);
            if (config.containsKey("content-type")) {
                content.setContentType(String.valueOf(config.get("content-type")));
            }else if(config.containsKey("charset")){
                content.setContentType(String.valueOf(config.get("charset")));
            }
            httpPost.setEntity(content);
            try(CloseableHttpResponse response = httpclient.execute(httpPost)){
                HttpEntity entify = response.getEntity();
                return new Result(EntityUtils.toString(entify));
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static final class Result{

        private String data;

        private Document document;

        public Result(String data){
            this.data = data;
        }

        public JSONObject getAsJson(){
            return JSON.parseObject(data);
        }

        public Object getXpath(String expr, QName returnType){
            try{
                if(document==null){
                    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                    dbf.setExpandEntityReferences(false);

                    DocumentBuilder builder = dbf.newDocumentBuilder();
                    Document document = builder.parse(new ByteArrayInputStream(data.getBytes("UTF-8")));
                    document.setXmlStandalone(true);

                    this.document = document;
                }

                // 生成XPath对象
                XPath xpath = XPathFactory.newInstance().newXPath();
                return xpath.evaluate(expr,document,returnType);
            }catch(Exception e){
                throw new RuntimeException(e);
            }
        }

        @Override
        public String toString() {
            return data;
        }
    }
}
